/*
 * This is an example of using the ADC to covert a single
 * analog input. The external input is to ADC10 channel A4.
 * This version triggers a conversion with regular WDT interrupts and
 * uses the ADC10 interrupt to copy the converted value to a variable in memory.
*/
#include "msp430g2553.h"
#define BUTTON 0x02	// P1.1
#define LED 0x01	// P1.0

// Define bit masks for ADC pin and channel, P1.4
#define ADC_INPUT 0x10
#define ADC_INCH INCH_4	//input channel
#define ARRAY_SIZE 50

void init_adc(void);
void init_timer(void);
void init_gpio(void);

// Global variable that store the results (read from the debugger)
volatile unsigned int ADCresult[ARRAY_SIZE];
// looks like 3.6V ~ 1024 from ADC
volatile unsigned int arrayPointer;

volatile int halfperiod;
volatile unsigned long conversion_count = 0; //total number of conversions done


void main()
{
	//WDTCTL = WDTPW + WDTHOLD;   	// Stop watchdog timer
	//BCSCTL1 = CALBC1_8MHZ;		// 8Mhz calibration for SMCLK
	//DCOCTL  = CALDCO_8MHZ;

	// WDT should interrupt every 8K/1.1Mhz ~ 7.5ms
	WDTCTL = (WDTPW + WDTTMSEL + WDTCNTCL + 0 + 1); // bits 1-0 = 01 => source/8K

	IE1 |= WDTIE;		// enable the WDT interrupt (in the system interrupt register IE1)

	button_state = 0;

	for(arrayPointer = 0; arrayPointer < ARRAY_SIZE; arrayPointer++)
		ADCresult[arrayPointer] = 0;	// initialize array to all 0's

	arrayPointer = 0;	// return pointer to beginning

	init_gpio();
	init_adc();

	_bis_SR_register(GIE + LPM0_bits);
}


void init_gpio()
{
	P1DIR |= LED;		// Set P1.0 to output direction
	P1OUT &= ~LED;		// initial state low

	P1DIR &= ~(BUTTON);	// Set P1.1 to input direction
	P1IES |= BUTTON;	// Set P1.1 to trigger interrupt going high to low
	P1IE |= BUTTON;		// enable P1.1 interrupts
}



void init_adc()
{
  ADC10CTL1 = ADC_INCH    		//input channel 4
			   + SHS_0 			//use ADC10SC bit to trigger sampling
			   + ADC10DIV_4 	// ADC10 clock/5
			   + ADC10SSEL_0 	// Clock Source=ADC10OSC, SSEL_3 is SMCLK
			   + CONSEQ_0; 		// single channel, single conversion

  ADC10AE0 = ADC_INPUT; 	// enable A4 analog input

  ADC10CTL0 = SREF_0    	//reference voltages are Vss and Vcc
	       	+ ADC10SHT_3 	//64 ADC10 Clocks for sample and hold time (slowest)
	       	+ ADC10ON    	//turn on ADC10
	       	+ ENC   	 	//enable (but not yet start) conversions
	       	//+ ADC10IE  		//enable interrupts
	       	+ ADC10SC;		//start conversion
}


// GPIO button handler
void interrupt button_handler(void)
{
	P1IFG &= ~BUTTON;		//reset interrupt flag

	P1OUT |= LED;			// turn LED on
}
ISR_VECTOR(button_handler,".int02") // declare interrupt vector



// handler for WDT
void interrupt WDT_interval_handler()
{
	//P1OUT ^= LED;
	// LED is toggled at 64.8 Hz (1/15ms) meaning handler called at half that frequency

	WDT_counter++;
	if(WDT_counter == 3)
	{
		P1OUT &= ~LED;	// turn LED off
		WDT_counter = 0;
	}
}
ISR_VECTOR(WDT_interval_handler, ".int10")



// handler for ADC, called when conversion is complete
void interrupt adc_handler()
{
	//while ((ADC10CTL1 & ADC10BUSY) != 0) {};	// wait for active conversion to complete
	conversion_count++;

	ADCresult[arrayPointer] = ADC10MEM;   // store the answer in our array
	arrayPointer++;				// advance the pointer

	//P1OUT ^= LED;
	// LED is toggled at the frequency 5.86 kHz when next conversion started every handler call
	// or 1/170us, meaning handler called at half that frequency

	ADC10CTL0 |= ADC10SC;			// start next conversion

	if(conversion_count == ARRAY_SIZE)
		arrayPointer += 0;	// just for a breakpoint
}
ISR_VECTOR(adc_handler, ".int05")

